using System;
using FireStarter.Base;
using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Test.BO.TestUtils;
using FireStarterModeller.Test;
using NUnit.Framework;
namespace Firestarter.DB.Schema.Test.BO
{
    [TestFixture]
    public partial class TestDBTable : TestBase
    {

        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = TestUtilsDBTable.CreateUnsavedValidDBTable();
            //---------------Assert Precondition----------------
            Assert.IsFalse(String.IsNullOrEmpty(dbTable.TableName), "TableName Should not be null");
            //---------------Execute Test ----------------------
            string actualToString = dbTable.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dbTable.TableName, actualToString);
        }
        [Test]
        public void Test_ToString_TableNameNull()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = TestUtilsDBTable.CreateUnsavedValidDBTable();
            dbTable.TableName = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dbTable.TableName), "TableName Should be null");
            //---------------Execute Test ----------------------
            string actualToString = dbTable.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dbTable.TableID.ToString(), actualToString);
        }
        [Test]
        public void Test_ToString_TableNameNull_TableIDNull()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = TestUtilsDBTable.CreateUnsavedValidDBTable();
            dbTable.TableName = null;
            dbTable.TableID = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dbTable.TableName), "TableName Should be null");
            Assert.IsNull(dbTable.TableID);
            //---------------Execute Test ----------------------
            string actualToString = dbTable.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual("-unnamed Table-", actualToString);
        }

        [Test]
        public void Test_DefaultPropertyValues()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DBTable dbTable = new DBTable();
            //---------------Test Result -----------------------
            Assert.AreEqual(ChangeType.None, dbTable.PendingChangeType);
        }

        [Test]
        public void TestGetColumnInfo_NullWhenNoColumnsExist()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dbTable.Columns.Count);
            //---------------Execute Test ----------------------
            string nonExistentColumn = TestUtilsShared.GetRandomString();
            DBColumn dbColumn = dbTable.GetColumn(nonExistentColumn);
            //---------------Test Result -----------------------
            Assert.IsNull(dbColumn);
        }

        [Test]
        public void TestGetColumnInfo_NullIfNotFound()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();

            DBColumn firstDBColumn = new DBColumn();
            firstDBColumn.ColumnName = "TestColumn1";
            dbTable.Columns.Add(firstDBColumn);

            DBColumn secondDBColumn = new DBColumn();
            secondDBColumn.ColumnName = "TestColumn2";
            dbTable.Columns.Add(secondDBColumn);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string nonExistentColumn = TestUtilsShared.GetRandomString();
            DBColumn dbColumn = dbTable.GetColumn(nonExistentColumn);
            //---------------Test Result -----------------------
            Assert.IsNull(dbColumn);
        }

        [Test]
        public void TestGetColumnInfo_ReturnsCorrectColumnInfoIfExists()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();

            DBColumn firstDBColumn = new DBColumn();
            firstDBColumn.ColumnName = "TestColumn1";
            dbTable.Columns.Add(firstDBColumn);

            DBColumn secondDBColumn = new DBColumn();
            secondDBColumn.ColumnName = "TestColumn2";
            dbTable.Columns.Add(secondDBColumn);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string existentColumnName = "TestColumn1";
            DBColumn foundDBColumn = dbTable.GetColumn(existentColumnName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundDBColumn);
            Assert.AreEqual(existentColumnName, foundDBColumn.ColumnName);
        }

        [Test]
        public void TestGetKeyInfo_NullWhenNoColumnsExist()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dbTable.Keys.Count);
            //---------------Execute Test ----------------------
            string nonExistentKey = TestUtilsShared.GetRandomString();
            DBKey dbKey = dbTable.GetKeyInfo(nonExistentKey);
            //---------------Test Result -----------------------
            Assert.IsNull(dbKey);
        }

        [Test]
        public void TestGetKeyInfo_NullIfNotFound()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();

            DBKey dbKeyForTable = new DBKey();
            dbKeyForTable.KeyName = "TestKey";
            dbTable.Keys.Add(dbKeyForTable);

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string nonExistentKey = TestUtilsShared.GetRandomString();
            DBKey dbKey = dbTable.GetKeyInfo(nonExistentKey);
            //---------------Test Result -----------------------
            Assert.IsNull(dbKey);
        }

        [Test]
        public void TestGetKeyInfo_ReturnsCorrectKeyInfoIfExists()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();

            DBKey firstDBKey = new DBKey();
            firstDBKey.KeyName = "TestKey1";
            dbTable.Keys.Add(firstDBKey);

            DBKey secondDBKey = new DBKey();
            string secondKeyInfoName = "TestKey2";
            secondDBKey.KeyName = secondKeyInfoName;
            dbTable.Keys.Add(secondDBKey);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DBKey foundDBKey = dbTable.GetKeyInfo(secondKeyInfoName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundDBKey);
            Assert.AreEqual(secondKeyInfoName, foundDBKey.KeyName);
        }


        [Test]
        public void TestGetForeignKeyInfo_NullWhenNoColumnsExist()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dbTable.ForeignKeys.Count);
            //---------------Execute Test ----------------------
            string nonExistentForeignKey = TestUtilsShared.GetRandomString();
            DBForeignKey dbForeignKey = dbTable.GetForeignKeyInfo(nonExistentForeignKey);
            //---------------Test Result -----------------------
            Assert.IsNull(dbForeignKey);
        }

        [Test]
        public void TestGetForeignKeyInfo_NullIfNotFound()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();

            DBForeignKey dbForeignKeyForTable = new DBForeignKey();
            dbForeignKeyForTable.ForeignKeyName = "TestForeignKeyColumn1";
            dbTable.ForeignKeys.Add(dbForeignKeyForTable);

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string nonExistentForeignKey = TestUtilsShared.GetRandomString();
            DBForeignKey dbForeignKey = dbTable.GetForeignKeyInfo(nonExistentForeignKey);
            //---------------Test Result -----------------------
            Assert.IsNull(dbForeignKey);
        }

        [Test]
        public void TestGetForeignKeyInfo_ReturnsCorrectColumnInfoIfExists()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable();

            DBForeignKey firstDBForeignKey = new DBForeignKey();
            firstDBForeignKey.ForeignKeyName = "TestForeignKeyColumn1";
            dbTable.ForeignKeys.Add(firstDBForeignKey);

            DBForeignKey secondDBForeignKey = new DBForeignKey();
            secondDBForeignKey.ForeignKeyName = "TestForeignKeyColumn2";
            dbTable.ForeignKeys.Add(secondDBForeignKey);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string existentForeignKeyName = "TestForeignKeyColumn2";
            DBForeignKey foundDBForeignKey = dbTable.GetForeignKeyInfo(existentForeignKeyName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundDBForeignKey);
            Assert.AreEqual(existentForeignKeyName, foundDBForeignKey.ForeignKeyName);
        }


        //[Test]
        //public void Test_GetClassName_ShouldConvertDBTableNameToClassName()
        //{
        //    //---------------Set up test pack-------------------
        //    DBTable dbTable = new DBTable("   TBLmy_table names ");
        //    DMSolution solution = CreateDMSolution();
        //    DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter(solution);
        //    dbToDMClassImporter.TableNamePrefix = "tbl";
        //    //---------------Assert Precondition----------------
        //    //---------------Execute Test ----------------------
        //    DMClass dmClass = dbToDMClassImporter.Import(dbTable);
        //    //---------------Test Result -----------------------
        //    Assert.IsNotNull(dmClass);
        //    Assert.AreEqual("MyTableName", dmClass.ClassNameBO);
        //}

        [Test]
        public void Test_GetClassNameFromPrimaryKey_WhenPrimaryKeyIsNull_ShouldReturnNull()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable(TestUtilsShared.GetRandomString());
            //---------------Assert Precondition----------------
            Assert.IsNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassNameFromPrimaryKey("");
            //---------------Test Result -----------------------
            Assert.IsNull(className);
        }

        [Test]
        public void Test_GetClassNameFromPrimaryKey_WhenPKColumnNameIsPascalCased_ShouldReturnPKColumnName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable(TestUtilsShared.GetRandomString());
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("MyClass");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassNameFromPrimaryKey("");
            //---------------Test Result -----------------------
            Assert.AreEqual("MyClass", className);
        }

        [Test]
        public void Test_GetClassNameFromPrimaryKey_PascalCasesColumnName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable(TestUtilsShared.GetRandomString());
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("my-class_thats different");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassNameFromPrimaryKey("");
            //---------------Test Result -----------------------
            Assert.AreEqual("MyClassThatsDifferent", className);
        }

        [Test]
        public void Test_GetClassNameFromPrimaryKey_RemovesIDSuffix()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable(TestUtilsShared.GetRandomString());
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("my Class id");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassNameFromPrimaryKey("ID");
            //---------------Test Result -----------------------
            Assert.AreEqual("MyClass", className);
        }

        [Test]
        public void Test_GetClassName_WhenPKColumnNameDoesNotMatchClassName_ShouldReturnTableName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable("tbmyclass");
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("My Column id");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassName("tb", "ID");
            //---------------Test Result -----------------------
            Assert.AreEqual("Myclass", className);
        }

        [Test]
        public void Test_GetClassName_WhenPKColumnNameSimilarToClassName_ShouldReturnImprovedTableName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable("tbmyclass");
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("My Class Column id");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassName("tb", "ID");
            //---------------Test Result -----------------------
            Assert.AreEqual("MyClass", className);
        }

        [Test]
        public void Test_GetClassName_WhenNameFromTableNameAlreadyPascalCased_ShouldReturnNameFromTableName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable("tbmyClass");
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("My ClaSs id");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassName("tb", "ID");
            //---------------Test Result -----------------------
            Assert.AreEqual("MyClass", className);
        }

        [Test]
        public void Test_GetClassName_WhenNameFromTableNameNotPascalCased_WithCompositePK_ShouldReturnNameFromTableName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = new DBTable("tbmyclass");
            DBTableBuilder dbTableBuilder = new DBTableBuilder(dbTable);
            dbTableBuilder.AddPrimaryKeyColumn("MyClass");
            dbTableBuilder.AddPrimaryKeyColumn("PkColumn2");
            //---------------Assert Precondition---------------
            Assert.IsNotNull(dbTable.PrimaryKeyDB);
            //---------------Execute Test ----------------------
            string className = dbTable.GetClassName("tb", "");
            //---------------Test Result -----------------------
            Assert.AreEqual("Myclass", className);
        }

    }
}